package server;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import utils.*;
import common.*;


public class RelayMessages implements OnRecieve
{
	private ClientServerMessage scm;
	private static RelayMessages instance = null;
	
	
	private Map<Integer, ServerSendMsg> ServerThreads;
	
	public RelayMessages(Map<Integer, ServerSendMsg> ServerThreads)
	{
		this.ServerThreads = ServerThreads;
	}
	
	public Map<Integer, ServerSendMsg>  getServerThreads()
	{
		return ServerThreads;
	}
	public static RelayMessages getInstance()
	{
		if(instance == null)
		{
			instance = new RelayMessages(new HashMap<Integer, ServerSendMsg>());
			return instance;
		}
		else
			return instance;
	}
	
	public synchronized void AddThread(int ClientID, ServerThread st)
	{
		ServerThreads.put(ClientID, st);
	}
	
	public synchronized boolean SendMessage(int SenderClientID, int ClientID, String Message)
	{
		String MessageFormated = SenderClientID + ":"+Message+"\n";
		/*is not signed on...*/
		boolean signedOnCurrentServers = false;
		List<ClientEntity> cliententity = Lists.getInstance().getLiveClientList();
		ClientEntity[] ClientList = cliententity.toArray(new ClientEntity[cliententity.size()]);
		
		for(int i = 0; i < ClientList.length; i ++)
		{
			if(ClientList[i].getId() == ClientID)
				signedOnCurrentServers = true;
		}
		if(!signedOnCurrentServers && SenderClientID != -1)
		{
			ServerThreads.get(SenderClientID).deliverMsg("Client not signed on\n");
			return false;
		}
		/*If the current server contains the destination client, deliver the message..*/
		if(ServerThreads.containsKey(ClientID))
		{
			PrintMsg.PrintStatic("Sending To Client", "ToClientID: " + ClientID + "\nFromClient: " + SenderClientID +"\n Message: "+ Message+ "\n");

			if(SenderClientID == -1)
				ServerThreads.get(ClientID).deliverMsg(Message);
			else
				ServerThreads.get(ClientID).deliverMsg(MessageFormated);
			return true;
		}
		/*else.. find the group, send it to the approate server..*/
		List<Entity> em = Lists.getInstance().responsibleServers(ClientID);	
		if(em != null && !em.isEmpty())
		{
				ServerMessage sm = new ServerMessage(ClientServerEnum.SERVER_2_SERVER_MESSAGE, ClientID+"", MessageFormated);
				Message m = new Message(sm.getServerMessage().getBytes());
				m.setDest(em.get(0));
				synchronized(ServerUDPSend.UDPSendBuffer)
				{
					ServerUDPSend.UDPSendBuffer.add(m);
				}
				PrintMsg.PrintStatic("Relay To Client", "Relay to Server IP: "+em.get(0).getIp()+"\nToClientID: " + ClientID + "\nFromClient: " + SenderClientID +"\n Message: "+ MessageFormated+ "\n");
		}
		
		return false;
	}

	@Override
	/*if we recieve a UDP message telling server to deliver a message to the client..*/
	public synchronized void RecieveUDP() 
	{
		String UDP_Msg;
		
			UDP_Msg = (String)new String(ServerUDPRead.UDPReadBuffer.remove().getData());
	
		ServerMessage sm = new ServerMessage(UDP_Msg);
		System.out.println(UDP_Msg);
		
		scm = new ClientServerMessage(UDP_Msg);
		switch(scm.getMessageType())
		{
			case SERVER_2_SERVER_MESSAGE:
				SendMessage(-1,sm.getClientID(),sm.getClientContent());
				break;
		}
	}
	
}
